/**
 * html的正文也就是分为标签, 属性, 嵌套 把html的信息拆分到json里面,
 * 对每个小结构的处理分为三种方法, appender和handler和generator,
 * generator 是一个完整结构的生产器;
 * append是追加器不能改变已有的字符串和定义信息, 只能往后拼接, 是基础;
 * handler是直接查看现有的字符串, 字符串和定义信息进行处理.
 *
 * 开发习惯约定
 * 字符串用单引号, 带空格的字符串空格放入下一节的开头.方法命名为: 操作主题+主题的修饰+方法类型 用驼峰法命名
 *
 * 选择器举例 $("#content").find("td[data_id='2']");
 * @param amountId
 * @param originTableDefinition
 * @param originColumnsDefinition
 * @param body
 */
class TableBuilder {
    constructor(amountId, originTableDefinition, originColumnsDefinition, data) {
        this.table = '';
        this.tHead = '';
        this.tbody = '';
        this.amountId = amountId;
        this.data = data;
        this.currentItem = undefined;
        this.originTableDefinition = originTableDefinition;
        this.originColumnsDefinition = originColumnsDefinition;
        this.tableDefinition = Object.assign({}, originTableDefinition)
        this.columnsDefinition = Object.assign([], originColumnsDefinition)
        this.rowCount = 0;
        this.columnNameDefinitions = [];
    }

    /**
     * 添加一行
     * @param data
     */
    addOneRow(data) {
        if (!data) {
            data = {};
        }
        let row = this.tbodyRowGenerator(data);
        $("#" + this.amountId).find("tbody").append(row);
    }

    /**
     * 移除一行
     * @param index
     */
    removeRow(index) {
        if (index > this.rowCount) {
            return;
        }
    }

    /**
     *  通过jquery的row元素对象移除数据
     * @param row
     */
    removeRowByJqueryRowObject(row) {
        let index = this.getIndexByJqueryRowObject(row);
        row.nextAll().remove();
        let parent = row.parent();
        row.remove();
        this.data.splice(index - 1, 1);
        this.rowCount = index - 1;
        for (let i = index; i < this.data.length; i++) {
            parent.append(this.tbodyRowGeneratorWithIndex(i, this.data[i]));
        }
    }

    /**
     * 根据前置按钮删除数据
     * @param obj
     */
    removeRowByPrefixButton(obj) {
        return this.removeRowByJqueryRowObject($(obj).parent().parent());
    }

    /**
     * 通过jquery的row元素对象获取index
     * @param row
     * @returns {*}
     */
    getIndexByJqueryRowObject(row) {
        return row.find('td[data_id]').text();
    }

    /**
     * 重写渲染自定行
     * @param index
     * @param data
     */
    reRender(index, data) {
        let jqueryObj = $("#" + this.amountId).find('td[data_id="' + index + '"]').parent();
        jqueryObj.replaceWith(this.tbodyRowGeneratorWithIndex(index, data));
    }

    /**
     * 构造html
     */
    build() {
        this.table = this.tablePreAppender();
        this.tHead += "<thead>";
        let tr = this.tHeadPreAppender(this.tableDefinition);
        let columnNameArray = [];
        for (let item of this.columnsDefinition) {
            tr += "<th>" + item['_title'] + "</th>";
            columnNameArray.push(item['_column']);
            this.columnNameDefinitions.push(item);
        }
        tr += '</tr>';
        this.tHead += tr + '</thead>';

        this.tbody += this.tbodyPreAppender();

        if (!!this.data && this.data.length > 0) {
            for (let item of this.data) {
                let row = this.tbodyRowGenerator(item);
                this.tbody += row;
            }
        }

        this.tbody += '</tbody>';
        this.table += this.tHead;
        this.table += this.tbody;
        this.table += "</table>";

        Log.debug(this.table);
        $("#" + this.amountId).empty().html(this.table);
    }

    /**
     *
     * @param item
     * @returns {string}
     */
    tbodyRowGenerator(item) {
        this.rowCount++;
        return this.tbodyRowGeneratorWithIndex(this.rowCount, item);
    }

    tbodyRowGeneratorWithIndex(index, item) {
        this.currentItem = item;
        let row = this.colPreAppender(index);
        for (let def of this.columnNameDefinitions) {
            let td = '';
            let showType = def['_showType'];
            if (!showType) {
                showType = 'content';
            }

            if (showType === 'content') {
                let type = def['_type'];
                td += this.columnPreAppender(def);
                if (type === 'input') {
                    td += this.genInputContent(item, def);
                } else {
                    td += this.getValue(item, def);
                }

            } else if (showType === 'index') {
                td += this.columnPreAppender(def);
                td += index;
            }

            if (showType === 'renderAll') {
                let renderFunction = def['_renderFunction'];
                row += eval(renderFunction + '(item , tableDefinition, index)');
            } else {
                td += this.columnPostAppender(def);
                row += td;
            }
        }
        row += this.colPostHandler(tableDefinition);
        return row;
    }

    /**
     * table前置追加器
     * @returns {string}
     */
    tablePreAppender() {
        let table = '<table';
        let _table = this.tableDefinition['_table'];
        if (!!_table) {
            table += HtmlUtils.idAttributeGenerator(_table);
            table += HtmlUtils.styleAttributeGenerator(_table);
            table += HtmlUtils.classAttributeGenerator(_table);
        }
        table += '>';
        return table;
    }

    /**
     * 表头前置追加器
     * @param tableDefinition
     */
    tHeadPreAppender(tableDefinition) {
        let tr = '';
        let _model = tableDefinition['_model'];
        if (!_model) {
            _model = 'normal';
        }
        if (_model === 'prefixButton') {
            console.log("开启前置新增删除按钮模式   ");
            tr += '<tr>';
            let _td = tableDefinition._modelAttribute?._head?._td;
            if (!!_td) {
                tr += this.tdStandardGenerator(_td);
            }
        } else {
            tr += '<tr>';
        }
        return tr;
    }

    /**
     * 表头后置处理器
     * @param tableDefinition
     */
    HeadPostHandler(tableDefinition, tr) {
        let model = tableDefinition['model'];
        if (!model) {
            model = 'normal';
        }
        if (model === 'prefixButton') {

        }
        tr += '</tr>';
        return tr;
    }

    /**
     * 行前置处理器
     * @param tableDefinition
     */
    colPreAppender(index) {
        let _model = this.tableDefinition['_model'];
        if (!_model) {
            _model = 'normal';
        }
        let tr = '<tr';
        tr += '>';
        tr += this.indexGenerator(index);
        if (_model === 'prefixButton') {
            let _td = this.tableDefinition._modelAttribute?._body?._td;
            if (!!_td) {
                tr += this.tdStandardGenerator(_td);
            }
        }
        return tr;
    }

    /**
     * 行后置处理器
     * @param tableDefinition
     */
    colPostHandler(tableDefinition) {
        return '</tr>';
    }

    /**
     * 栏前置处理器
     */
    columnPreAppender(def) {
        let bodyClass = def['_bodyClass'];
        let td = '<td';
        if (!!bodyClass) {
            td += ' class="' + bodyClass + '"';
        }

        let _attribute = def['attribute'];
        if (!!_attribute) {
            td += HtmlUtils.styleAttributeGenerator(_attribute);
            td += this.appendEventsInfo(_attribute);
        }
        td += '>'
        return td;
    }

    /**
     * 栏后置处理器
     */
    columnPostAppender() {
        return '</td>';
    }


    /**
     * 追加events信息
     * @param definitionObj
     * @returns {string}
     */
    appendEventsInfo(definitionObj) {
        let str = '';
        let events = definitionObj['events'];
        if (!!events) {
            for (let event of events) {
                if (this.tableDefinition._model === 'readonly' && (event.name === 'onclick' || event.name === 'ondblclick')) {
                    continue;
                }
                str += ' ' + event.name + '=' + event.fun;
                let params = event['params'];
                if (!params) {
                    str += '();';
                } else {
                    str += '(' + params + ');';
                }
            }
        }
        return str;
    }

    /**
     * 获取值
     * @param item
     * @param def
     * @returns {string}
     */
    getValue(item, def) {
        let _column = def['_column'];
        let value = item[_column];
        if (value === undefined) {
            let _defaultValue = def['_defaultValue'];
            if (_defaultValue != undefined) {
                value = _defaultValue;
            } else {
                value = '';
            }
        }
        return value;
    }

    /**
     * 生成input内容
     * @param item
     * @param def
     * @returns {string}
     */
    genInputContent(item, def) {
        let input = '<input';

        let column = def['_column'];
        input += ' name="' + column + '"';

        let inputAttribute = def['_inputAttribute'];
        if (!!inputAttribute) {
            input += this.appendHtmlTagAttribute(inputAttribute, "input");
        }

        let value = this.getValue(item, def);
        if (undefined !== value && '' !== value) {
            input += ' value="' + value + '"';
        }
        input += '/>';
        return input;
    }

    /**
     *  标准的td生成器
     * @param _td
     * @returns {undefined}
     */
    tdStandardGenerator(_td) {
        let td = '<td';
        let attribute = _td['attribute'];
        td += this.appendHtmlTagAttribute(attribute, "td");
        td += '>';
        let children = _td['children'];
        if (!!children) {
            for (let child of children) {
                td += this.htmlElementStandardGenerator(child);
            }
        }
        td += '</td>';
        return td;
    }

    /**
     * 标准的html元素生成器
     * @param elementDefinition
     */
    htmlElementStandardGenerator(elementDefinition) {
        let tag = elementDefinition.tag;
        if (!tag) {
            throw new DOMException("标准的html元素定义必须含有tag字段");
        }
        if (tag === '_text') {
            //_text的tag只输出文本
            return elementDefinition['text'];
        }
        let element = '';
        element += '<' + tag;
        let attribute = elementDefinition.attribute;
        if (!!attribute) {
            element += this.appendHtmlTagAttribute(attribute, tag);
        }
        element += '>';
        let children = elementDefinition['children'];
        if (!!children) {
            for (let child of children) {
                element += this.htmlElementStandardGenerator(child);
            }
        }
        element += '</' + tag + '>';
        return element;
    }

    /**
     * 追加html标签的属性
     * @param attribute
     * @returns {*}
     */
    appendHtmlTagAttribute(attribute, tag) {
        let element = '';
        element += HtmlUtils.classAttributeGenerator(attribute);
        element += HtmlUtils.styleAttributeGenerator(attribute);
        element += HtmlUtils.idAttributeGenerator(attribute);
        element += HtmlUtils.titleAttributeGenerator(attribute);
        element += HtmlUtils.valueAttributeGenerator(attribute);
        element += HtmlUtils.attributeGenerator(attribute, 'name');
        element += HtmlUtils.attributeGenerator(attribute, 'type');
        element += HtmlUtils.attributeGenerator(attribute, 'placeholder');
        element += this.appendEventsInfo(attribute);

        let _value = attribute._value;
        if (!!_value) {
            let _valueType = attribute._valueType;
            if (_valueType === 'columnValue') {
                let value = this.currentItem[_value];
                element += HtmlUtils.attributeSetter("value", value);
            }
        }
        if (tag === 'input' && attribute.readonly !== undefined) {
            element += ' readonly';
        }
        if (this.tableDefinition._model === 'readonly' && tag === 'input') {
            if (attribute.readonly === undefined) {
                element += ' readonly';
            }
        }
        return element;
    }

    tbodyPreAppender() {
        let tbody = '<tbody';
        let attribute = this.tableDefinition._modelAttribute?._body?.attribute;
        if (!!attribute) {
            tbody += this.appendHtmlTagAttribute(attribute, 'tbody');
        }
        tbody += '>';
        return tbody;
    }

    /**
     *行索引生成器
     * @returns {string}
     */
    indexGenerator(index) {
        return '<td style="display:none;" data_id="' + index + '">' + index + '</td>';
    }
}
